import sharp from 'sharp'
import path from 'path'
import fs from 'fs'

/**
 * 图片压缩配置
 */
interface CompressionOptions {
  /** 目标文件大小（KB），默认500KB */
  targetSizeKB?: number
  /** 最大宽度，默认1920 */
  maxWidth?: number
  /** 最大高度，默认1080 */
  maxHeight?: number
  /** JPEG质量，默认80 */
  quality?: number
  /** 是否保持宽高比，默认true */
  keepAspectRatio?: boolean
}

/**
 * 压缩图片到指定大小
 * @param inputPath 输入文件路径
 * @param outputPath 输出文件路径
 * @param options 压缩选项
 */
export async function compressImage(
  inputPath: string,
  outputPath: string,
  options: CompressionOptions = {}
): Promise<void> {
  const {
    targetSizeKB = 500,
    maxWidth = 1920,
    maxHeight = 1080,
    quality = 80,
    keepAspectRatio = true
  } = options

  try {
    // 确保输出目录存在
    const outputDir = path.dirname(outputPath)
    if (!fs.existsSync(outputDir)) {
      fs.mkdirSync(outputDir, { recursive: true })
    }

    // 获取图片信息
    const image = sharp(inputPath)
    const metadata = await image.metadata()
    
    console.log(`压缩图片: ${inputPath}`)
    console.log(`原始尺寸: ${metadata.width}x${metadata.height}`)
    console.log(`原始格式: ${metadata.format}`)

    // 计算新尺寸
    let newWidth = metadata.width || maxWidth
    let newHeight = metadata.height || maxHeight

    if (newWidth > maxWidth || newHeight > maxHeight) {
      if (keepAspectRatio) {
        const widthRatio = maxWidth / newWidth
        const heightRatio = maxHeight / newHeight
        const ratio = Math.min(widthRatio, heightRatio)
        
        newWidth = Math.round(newWidth * ratio)
        newHeight = Math.round(newHeight * ratio)
      } else {
        newWidth = Math.min(newWidth, maxWidth)
        newHeight = Math.min(newHeight, maxHeight)
      }
    }

    console.log(`目标尺寸: ${newWidth}x${newHeight}`)

    // 开始压缩，尝试不同的质量设置
    let currentQuality = quality
    let attempts = 0
    const maxAttempts = 5
    const targetSizeBytes = targetSizeKB * 1024

    while (attempts < maxAttempts) {
      attempts++
      
      // 处理图片
      let processedImage = image
        .resize(newWidth, newHeight, {
          fit: 'inside',
          withoutEnlargement: true
        })

      // 根据格式进行压缩
      if (metadata.format === 'png') {
        // PNG格式，转换为JPEG以获得更好的压缩率
        processedImage = processedImage
          .jpeg({ 
            quality: currentQuality,
            progressive: true,
            mozjpeg: true
          })
      } else if (metadata.format === 'webp') {
        // WebP格式
        processedImage = processedImage
          .webp({ 
            quality: currentQuality,
            effort: 6
          })
      } else {
        // 默认JPEG格式
        processedImage = processedImage
          .jpeg({ 
            quality: currentQuality,
            progressive: true,
            mozjpeg: true
          })
      }

      // 保存到临时文件检查大小
      const tempPath = outputPath + '.temp'
      await processedImage.toFile(tempPath)
      
      // 检查文件大小
      const stats = fs.statSync(tempPath)
      const fileSizeKB = stats.size / 1024
      
      console.log(`尝试 ${attempts}: 质量=${currentQuality}, 大小=${fileSizeKB.toFixed(2)}KB`)

      if (stats.size <= targetSizeBytes || currentQuality <= 20) {
        // 达到目标大小或质量已经很低了，使用这个结果
        fs.renameSync(tempPath, outputPath)
        console.log(`压缩完成: ${fileSizeKB.toFixed(2)}KB (质量: ${currentQuality})`)
        break
      } else {
        // 文件还是太大，降低质量重试
        fs.unlinkSync(tempPath)
        currentQuality = Math.max(20, currentQuality - 15)
      }
    }

    if (attempts >= maxAttempts) {
      throw new Error(`无法将图片压缩到目标大小 ${targetSizeKB}KB`)
    }

  } catch (error) {
    console.error('图片压缩失败:', error)
    throw error
  }
}

/**
 * 压缩上传的图片文件
 * @param file multer文件对象
 * @param options 压缩选项
 */
export async function compressUploadedImage(
  file: Express.Multer.File,
  options: CompressionOptions = {}
): Promise<void> {
  const inputPath = file.path
  const outputPath = file.path // 覆盖原文件
  
  await compressImage(inputPath, outputPath, options)
}

/**
 * 为聊天室封面图片压缩（较小尺寸）
 */
export async function compressCoverImage(file: Express.Multer.File): Promise<void> {
  await compressUploadedImage(file, {
    targetSizeKB: 300,
    maxWidth: 1280,
    maxHeight: 720,
    quality: 75
  })
}

/**
 * 为聊天室消息图片压缩（中等尺寸）
 */
export async function compressChatImage(file: Express.Multer.File): Promise<void> {
  await compressUploadedImage(file, {
    targetSizeKB: 400,
    maxWidth: 1024,
    maxHeight: 768,
    quality: 80
  })
}

/**
 * 为礼物图标压缩（小尺寸）
 */
export async function compressGiftIcon(file: Express.Multer.File): Promise<void> {
  await compressUploadedImage(file, {
    targetSizeKB: 100,
    maxWidth: 256,
    maxHeight: 256,
    quality: 85
  })
}

/**
 * 为广告图片压缩（大尺寸但控制文件大小）
 */
export async function compressAdvertisementImage(file: Express.Multer.File): Promise<void> {
  await compressUploadedImage(file, {
    targetSizeKB: 600,
    maxWidth: 1920,
    maxHeight: 1080,
    quality: 80
  })
}
